const robot = require('robotjs');
const fs = require('fs');
const { PNG } = require('pngjs');

const Tesseract = require('tesseract.js');
const dayjs=require('dayjs');
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

const { execSync } = require('child_process');

//粘贴
function pasteFromClipboard(text) {
    try {
        // Windows 系统，使用 powershell 命令复制文本到剪贴板
        // 对单引号进行转义
        const escapedText = text.replace(/'/g, "''");
        // 使用 Out-String 确保换行符被正确处理
        execSync(`powershell -command "Write-Output '${escapedText}' | Out-String -Stream | Set-Clipboard"`);
        robot.keyTap('v','control')
    } catch (error) {
        console.error('复制到剪贴板失败:', error);
    }
    // Windows 系统

}
const rectView={
    getValueByPosArr(posArr,rect){
        return rect.data[posArr[0]+posArr[1]*rect.width]
    },
    //通过花费得到的收益
    initItem(item,all){
        const rect1=this.rect1
        const rect2=this.rect2
        const posArr1=this.posArr1
        const posArr2=this.posArr2

        while(item.price>0){
            const pos1=[posArr1[item.id][0]+posArr2[item.curFee][0],posArr1[item.id][1]+posArr2[item.curFee][1]]
            const pos2=posArr2[item.curFee]
            item.curFee++
            item.price--
            if(this.getValueByPosArr(pos1,rect1)===this.getValueByPosArr(pos2,rect2)){
                item.val++
            }else if(!all){
                break
            }else if(all!==true){
                all--
            }
        }
    },
    //大图中查找小图,获取最大的相似区域
    getMaxList(rect1,rect2,pipei){
        this.rect1=rect1
        this.rect2=rect2
        this.posArr1=[]
        this.posArr2=[]
        this.taskList=[]
        const posArr1=this.posArr1
        const posArr2=this.posArr2


// 初始化任务列表
        let taskList=this.taskList
        let id = 0;

        const len2=rect2.width*rect2.height
// 遍历 bigRect 的每个像素点，生成任务
        const h1=rect1.height-rect2.height+1
        const w1=rect1.width-rect2.width+1
        for (let y = 0; y < h1; y++) {
            for (let x = 0; x < w1; x++) {
                posArr1.push([x,y])
                taskList.push({
                    id: id,          // 唯一任务 ID
                    price: len2,     // 价格
                    curFee:0,   //花费
                    val:0,    //价值
                });
                id++
            }
        }
        for (let y = 0; y < rect2.height; y++) {
            for (let x = 0; x < rect2.width; x++) {
                posArr2.push([x,y])
            }
        }

        //一直找到val最大的，
        let maxVal=0

        let isRunning=true

        while (isRunning){
            let maxList=[]
            taskList.forEach( (item)=>{
                this.initItem(item)
                if (item.val > maxVal) {
                    maxVal = item.val
                    maxList=[item]
                }else if (item.val === maxVal) {
                    maxList.push(item)
                }
            })
            if(taskList.length===maxList.length){
                maxList=[]
                taskList.forEach((item)=>{
                    this.initItem(item,10)
                    if (item.val > maxVal) {
                        maxVal = item.val
                        maxList=[item]
                    }else if (item.val === maxVal) {
                        maxList.push(item)
                    }
                })
            }
            if(taskList.length===maxList.length||maxList.length==0){
                isRunning=false
            }else{
                taskList=maxList
            }

        }

        if(taskList.length){
            taskList.forEach((item)=>{
                item.x=posArr1[item.id][0]
                item.y=posArr1[item.id][1]
                item.width=rect2.width
                item.height=rect2.height
                item.pipei=parseInt((item.val*100/item.curFee))
            })
        }
        console.log(taskList.length)
        return taskList


    },

}
const utils={
    async hideAllWindows(){
        // 获取屏幕尺寸
        const screenSize = robot.getScreenSize();
        const width = screenSize.width;
        const height = screenSize.height;
        // console.log('屏幕宽度:', width, '屏幕高度:', height);
        robot.moveMouse(width,height)
        robot.mouseClick()
    },
    getRectInScreen(imgInfo){
        const width = imgInfo.width;
        const height = imgInfo.height;
        const screenshot = robot.screen.capture(imgInfo.x, imgInfo.y, width, height);
        const rect={
            width: width,
            height: height,
            data:[]
        }
        // 将截图数据复制到 PNG 对象
        for (let y = 0; y < height; y++) {
            for (let x = 0; x < width; x++) {
                const pos = y * width + x;
                const imgPos = pos * 4;
                const r=screenshot.image.readUInt8(imgPos + 2)
                const g=screenshot.image.readUInt8(imgPos + 1)
                const b=screenshot.image.readUInt8(imgPos)
                rect.data[pos]=parseInt((r+b+g)/3)
            }
        }
        return rect
    },
    //获取屏幕截图
    getCroppedPngInScreen(imgInfo){
        const screenshot = robot.screen.capture(imgInfo.x, imgInfo.y, imgInfo.width, imgInfo.height);
        // 根据 imgInfo 裁剪截图
        const croppedPng = new PNG({
            width: imgInfo.width,
            height: imgInfo.height
        });
        for (let y = 0; y < croppedPng.height; y++) {
            for (let x = 0; x < croppedPng.width; x++) {
                const pos = y * croppedPng.width + x;
                const imgPos = pos * 4;
                const r=screenshot.image.readUInt8(imgPos + 2)
                const g=screenshot.image.readUInt8(imgPos + 1)
                const b=screenshot.image.readUInt8(imgPos)
                const a=screenshot.image.readUInt8(imgPos+3)
                croppedPng.data[imgPos] = r; // Red
                croppedPng.data[imgPos + 1] = g; // Green
                croppedPng.data[imgPos + 2] = b; // Blue
                croppedPng.data[imgPos + 3] = a; // Alpha
            }
        }

        return croppedPng
    },
    getLocalRect(f1){
        const t1Buffer = fs.readFileSync(f1);
        const t1Png = PNG.sync.read(t1Buffer);
        const height=t1Png.height
        const width=t1Png.width
        const rect={
            width: width,
            height: height,
            data:[]
        }
        for (let y = 0; y < height; y++) {
            for (let x = 0; x < width; x++) {
                const pos = y * width + x;
                const imgPos = pos * 4;
                const r=t1Png.data[imgPos]
                const g=t1Png.data[imgPos + 1]
                const b=t1Png.data[imgPos + 2]
                rect.data[pos]=parseInt((r+b+g)/3)
            }
        }
        return rect
    },
    compareRect(bigRect,smallRect){
        const bigData=bigRect.data
        const smallData=smallRect.data
        let num=0
        let len=0
        for (let y = 0; y < smallRect.height; y++) {
            for (let x = 0; x < smallRect.width; x++) {
                const pos = (y * bigRect.width + x)
                if(bigData[pos]===smallData[pos]){
                    num++
                }
                len++
            }
        }
        return (num*100/len)
    },

    async getTextByImgInScreenShot(imgInfo,img){
        const croppedPng=this.getCroppedPngInScreen(imgInfo)
        // 将 PNG 对象转换为 Uint8Array
        const pngBuffer = PNG.sync.write(croppedPng);
        if('./img/page-arbr.png'===img){
            fs.writeFileSync('./img/arbr-test.png', pngBuffer);
        }
        if('./img/page-macd.png'===img){
            fs.writeFileSync('./img/macd-test.png', pngBuffer);
        }
        if('./img/page-kdj.png'===img){
            fs.writeFileSync('./img/kdj-test.png', pngBuffer);
        }
        //识别屏幕中imgInfo位置的文字
        const res=await Tesseract.recognize(
            new Uint8Array(pngBuffer),
            'eng',
        )
        return res.data.text.trim()
    },

}

const config={
    imgInfoMap:{},
    rectMap:{}
}


const view={
    updateImgConfig(img){
        const screenSize=robot.getScreenSize()
        const screenRect=utils.getRectInScreen({x:0,y:0,width:screenSize.width,height:screenSize.height})
        const smaRect=utils.getLocalRect(img)
        const list=rectView.getMaxList(screenRect,smaRect)
        if(list.length===1&&list[0].pipei===100){
            const imgInfo=list[0]
            config.imgInfoMap[img]=imgInfo
            config.rectMap[img]=smaRect
        }
    },
    //获取图片信息在屏幕中的位置
    getImgInfoInScreenShot(f1){
        const imgInfo=config.imgInfoMap[f1]
        const smaRect=config.rectMap[f1]

        const bigRect=utils.getRectInScreen(imgInfo)
        const pipei =utils.compareRect(bigRect,smaRect)
        console.log('是否匹配',pipei,imgInfo.x,imgInfo.y,pipei)
        if(pipei>90){
            return imgInfo
        }else{
            console.log('匹配图片失败',f1)

        }
    },
    //识别图片位置中的文字
    async getTextByImg(img){
        const topImgInfo=config.imgInfoMap[img]
        return await utils.getTextByImgInScreenShot(topImgInfo,img)
    },
    //列表可用的
    codeMap:{
        'SH2509':{
            codeName:'烧碱2509',
        },
        'SA2509':{
            codeName:'纯碱2509',
        },
        'SA2601':{
            codeName:'纯碱2601',
        },
        'UR2509':{
            codeName:'尿素2509',
            onlyDay:true,//只有白天有
        },
        '202509':{
            codeName:'氧化铝2509',
        },
    },
    isAutoPage:false,
    async showQHPage(){
        await utils.hideAllWindows()
        await delay(500)
        const imgInfo=this.clickImgInScreen('./img/qhicon.png')
        await delay(2000)
        if(imgInfo){
            this.isAutoPage=this.getImgInfoInScreenShot('./img/page-top.png')
        }
    },
    async login(task){
        const imgInfo=this.getImgInfoInScreenShot(task.img)
        if(imgInfo){
            robot.moveMouse(imgInfo.x+imgInfo.width/2,imgInfo.y+imgInfo.height-20)
            robot.mouseClick()
        }else{
            await delay(1000)
            await this.login(task)
        }
    },

    async initConfig(){
        if(fs.existsSync('./config.json')){
            const cacheConfig=JSON.parse(fs.readFileSync('./config.json','utf-8'))
            Object.assign(config,cacheConfig)
        }else{
            //生成imgInfoMap
            const screenList=[
                {
                    screenImg:'./img/page-screen.png',
                    type:'imgInfo',
                    list:[
                        './img/page-item1.png',
                        './img/page-item2.png',
                        './img/page-item3.png',
                        './img/page-item4.png',
                        './img/page-item5.png',
                        './img/page-macd.png',
                        './img/page-kdj.png',
                        './img/page-arbr.png',
                    ]
                },
                {
                    screenImg:'./img/page-screen.png',
                    list:[
                        './img/page-top.png',
                    ]
                },
                {
                    screenImg:'./img/icons-screen.png',
                    list:[
                        './img/qhicon.png',
                        './img/qqicon.png',
                        './img/qqmsg.png',
                    ]
                }
            ]
            for(let i=0;i<screenList.length;i++){
                const item=screenList[i]
                const screenImg=item.screenImg
                const itemList=item.list
                const screenRect=utils.getLocalRect(screenImg)
                for(let i=0;i<itemList.length;i++){
                    const img=itemList[i]
                    const smaRect=utils.getLocalRect(img)
                    const list=rectView.getMaxList(screenRect,smaRect)
                    if(list.length===1&&list[0].pipei===100){
                        const imgInfo=list[0]
                        if(item.type==='imgInfo'){
                            config.imgInfoMap[img]=imgInfo
                        }else{
                            config.imgInfoMap[img]=imgInfo
                            config.rectMap[img]=smaRect
                        }

                    }else{
                        throw new Error('图片匹配失败'+img)
                    }
                }
            }
            fs.writeFileSync('./config.json',JSON.stringify(config,null,2))
            console.log('配置ok,生成图片信息')
        }

    },

    clickImgInScreen(img){
        let imgInfo=this.getImgInfoInScreenShot(img)

        if(imgInfo){
            robot.moveMouse(imgInfo.x+imgInfo.width/2,imgInfo.y+imgInfo.height/2)
            robot.mouseClick()
            return imgInfo
        }
    },
    msgList:[],

    async qqSendMsg(text=''){

        await utils.hideAllWindows()
        const has1=this.clickImgInScreen('./img/qqicon.png')
        await delay(200)

        if(has1){
            this.clickImgInScreen('./img/qqmsg.png')
            pasteFromClipboard(text)

            await delay(500)
            if(!this.isDev){
                robot.keyTap('enter')
            }
            await delay(500)
        }
    },
    codeList:[],
    async listenAllCodeInit(task){
        const codeList=this.codeList
        if(this.isAutoPage){
            console.log('进入期货界面')

            const list=[
                './img/page-item1.png',
                './img/page-item2.png',
                './img/page-item3.png',
                './img/page-item4.png',
                './img/page-item5.png',
            ]
            for(let i=0;i<list.length;i++){
                const img=list[i]
                const text=await this.getTextByImg(img)
                const arr=text.split('\n')
                const arr1=arr[0].split(' ')
                const arr2=arr[1].split(' ')
                const code=arr2[0]
                const price=arr1[arr1.length-1]
                console.log('识别list：',arr)
                if(this.codeMap[code]){
                    Object.assign(this.codeMap[code],{
                        code:code,
                        img:img,
                        price:price,
                    })
                    codeList.push(this.codeMap[code])
                }

            }
        }
    },
    //delayEmptyTime
    async delayEmptyTime(){
        const now = dayjs();
        const nowTime = now.valueOf();
        const day = dayjs().day();

        const nineAm = dayjs(now.format('YYYY-MM-DD 09:00:00')).valueOf();
        const elevenThirtyAm = dayjs(now.format('YYYY-MM-DD 11:30:00')).valueOf();
        const oneThirtyPm = dayjs(now.format('YYYY-MM-DD 13:30:00')).valueOf();
        const threePm = dayjs(now.format('YYYY-MM-DD 15:00:00')).valueOf();
        const ninePm = dayjs(now.format('YYYY-MM-DD 21:00:00')).valueOf();
        const elevenPm = dayjs(now.format('YYYY-MM-DD 23:00:00')).valueOf();
        const nextDayNineAm = dayjs(now.add(1, 'day').format('YYYY-MM-DD 09:00:00')).valueOf();

        if(day === 6 || day === 0){
            const durTime = nextDayNineAm - nowTime;
            console.log('等待第二天09:00', durTime);
            await delay(durTime);
        }else if (nowTime < nineAm) {
            const durTime = nineAm - nowTime;
            console.log('等待9:00', durTime);
            await delay(durTime);
        } else if (nowTime > elevenThirtyAm && nowTime < oneThirtyPm) {
            const durTime = oneThirtyPm - nowTime;
            console.log('等待13:30', durTime);
            await delay(durTime);
        } else if (nowTime > threePm && nowTime < ninePm) {
            const durTime = ninePm - nowTime;
            console.log('等待21:00', durTime);
            await delay(durTime);
        } else if (nowTime > elevenPm) {
            const durTime = nextDayNineAm - nowTime;
            console.log('等待第二天09:00', durTime);
            await delay(durTime);
        }
    },
    async _getSignalData(code,codeName){
        const macdText=await this.getTextByImg('./img/page-macd.png')
        const kdjText=await this.getTextByImg('./img/page-kdj.png')
        const arbrText=await this.getTextByImg('./img/page-arbr.png')

        const signal={
            DIFF:'',
            DEA:'',
            MACD:'',
            K:'',
            D:'',
            J:'',
            AR:'',
            BR:''
        }
        const [DIFFStr,DEAStr,MACDStr]=macdText.split(' ').filter(x=>x.length>2)
        const [KStr,DStr,JStr]=kdjText.split(' ').filter(x=>x.length>2)
        const [ARStr,BRStr]=arbrText.split(' ').filter(x=>x.length>2)

        if(this.isLog){
            console.log(macdText,kdjText,arbrText,signal)
        }
        return signal
    },
    async getSignalData(task){
        const {
            DIFF, DEA, MACD,
            K, D, J,
            AR, BR
        }=await this._getSignalData(task)
        let tip=""
        //提示冲顶，准备空
        if(MACD>=3&&DEA>MACD&&DIFF>DEA+1){
            tip=`提示冲顶，准备空 MACD:${MACD} ${DEA} ${DIFF}`
        }
        //提示到顶，空
        if(MACD>=1&&MACD<3&&DEA>MACD&&DIFF>DEA+1){
            tip=`提示到顶，空 MACD:${MACD} ${DEA} ${DIFF}`
        }
        //提示急跌，空
        if(MACD<-1&&DEA>1&&DIFF>DEA-1){
            tip=`提示急跌，空 MACD:${MACD} ${DEA} ${DIFF}`
        }

        //提示冲底，准备多
        if(MACD<=-3&&DEA<MACD&&DIFF<DEA-1){
            tip=`提示冲底，准备多 MACD:${MACD} ${DEA} ${DIFF}`
        }
        //提示到底，多
        if(MACD<=-1&&MACD>-3&&DEA<MACD&&DIFF<DEA-1){
            tip+=`提示到底，多 MACD:${MACD} ${DEA} ${DIFF}`
        }

        //提示急涨，多
        if(MACD>1&&DEA<-1&&DIFF<DEA+1){
            tip+=`提示急涨，多 MACD:${MACD} ${DEA} ${DIFF}`
        }
        //情绪过低，多
        if(AR>0&&BR>0&&(AR<50||BR<50)){
            tip+=`情绪过低，多 ARBR:${AR} ${BR}`
        }
        //情绪过高，空
        if(AR>180&&BR>180){
            tip+=`情绪过高，空 ARBR:${AR} ${BR}`
        }
        if(this.isTestSignal){
            this.isTestSignal=false
            tip+=`测试 MACD:${MACD} ${DEA} ${DIFF}`
            tip+=`测试 ARBR:${AR} ${BR}`
        }

        if(tip){
            const text=await this.getTextByImg(task.img)
            const arr=text.split('\n')
            const arr1=arr[0].split(' ')
            const arr2=arr[1].split(' ')
            const code=arr2[0]
            const price=arr1[arr1.length-1]
            if(code===task.code){
                return {
                    time:new Date().getTime(),
                    tip:tip,
                    code:task.code,
                    price,
                    codeName:task.codeName,
                }
            }

        }
    },
    isTestSignal:false,
    preSignalMap:{},
    async listenAllCodeList(task){
        while (this.isAutoPage) {
            const codeList = this.codeList;
            const curTime = dayjs().format('HH:mm:ss');
            for (let i = 0; i < codeList.length; i++) {
                const taskItem = codeList[i];
                if(taskItem.onlyDay&&curTime>'15:00:00'){
                    continue
                }

                const imgInfo = config.imgInfoMap[taskItem.img];
                robot.moveMouse(imgInfo.x + imgInfo.width / 2, imgInfo.y + imgInfo.height / 2);
                robot.mouseClick();
                await delay(1000);
                console.log('监听：', taskItem.code);
                const signal = await this.getSignalData(taskItem);
                if (signal) {
                    const preSignal = this.preSignalMap[signal.code];
                    if (preSignal &&preSignal.tip===signal.tip) {
                        // 不做处理
                        Object.assign(preSignal,signal)
                    } else {
                        this.msgList.push(signal);
                    }
                    this.preSignalMap[signal.code] = signal;
                    console.log('存在信号', signal);
                    break
                }
            }

            this.isAutoPage = this.getImgInfoInScreenShot('./img/page-top.png');

            await this.sendMSG()

            await this.delayEmptyTime();
        }
    },
    //间隔1分钟发送一次信号
    async sendMSG(){
        const fiveMinutesInMs = 1 * 60 * 1000;
        if (this.msgList.length) {
            const nowTime = new Date().getTime();
            if (!this.preTime || nowTime - this.preTime > fiveMinutesInMs) {
                this.preTime = nowTime;
                const tarr = [dayjs().format('YYYY-MM-DD HH:mm:ss ')];
                this.msgList.forEach(({codeName, tip,price}) => {
                    tarr.push(`${codeName}:${price} -> ${tip}`);
                });
                this.msgList = [];
                this.preSignalMap={}
                await this.qqSendMsg(tarr.join(' '));
                await this.showQHPage();
            }
        }
    },
    isDev:true,
    isLog:true,
    async init(){
        // const screenSize=robot.getScreenSize()
        // console.log(screenSize)
        await this.initConfig()
        // await this.delayEmptyTime()

        await this.showQHPage()
        await this.listenAllCodeInit()
        await this.listenAllCodeList()
        // await this.qqSendMsg('测试信息')
        await utils.hideAllWindows()
        console.log('程序退出结束')
    },
}

view.init()

